From f52f3442e910dea70073effc292e8ee0c5ddc177 Mon Sep 17 00:00:00 2001 From: sgranjoux Date: Sun, 30 Mar 2008 17:57:25 +0000 Subject: [PATCH] * plugins/debug-manager/anjuta-debug-manager.glade, plugins/debug-manager/command.c, plugins/debug-manager/command.h, plugins/debug-manager/start.c, plugins/gdb/plugin.c, plugins/gdb/debugger.c, plugins/gdb/debugger.h, libanjuta/interfaces/libanjuta.idl: Improve start program dialog, allowing to specify working directory and environment variables git-svn-id: http://svn.gnome.org/svn/anjuta/trunk@3804 1dbfb86a-d425-0410-a06b-cb591aac69f6 --- ChangeLog | 13 + libanjuta/interfaces/libanjuta.idl | 26 +- plugins/debug-manager/anjuta-debug-manager.glade | 128 ++++- plugins/debug-manager/command.c | 59 ++- plugins/debug-manager/command.h | 2 + plugins/debug-manager/start.c | 582 +++++++++++++++++------ plugins/gdb/debugger.c | 39 ++ plugins/gdb/debugger.h | 4 + plugins/gdb/plugin.c | 22 + 9 files changed, 707 insertions(+), 168 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e9c13cd..6a9c82fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-03-30 Sébastien Granjoux + + * plugins/debug-manager/anjuta-debug-manager.glade, + plugins/debug-manager/command.c, + plugins/debug-manager/command.h, + plugins/debug-manager/start.c, + plugins/gdb/plugin.c, + plugins/gdb/debugger.c, + plugins/gdb/debugger.h, + libanjuta/interfaces/libanjuta.idl: + Improve start program dialog, allowing to specify working + directory and environment variables + 2008-03-26 Naba Kumar * libanjuta/resources.c (anjuta_res_url_show): Use diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl index d57ff9e6..74fe416f 100644 --- a/libanjuta/interfaces/libanjuta.idl +++ b/libanjuta/interfaces/libanjuta.idl @@ -3108,7 +3108,31 @@ interface IAnjutaDebugger * Returns: TRUE if sucessful, other FALSE. */ gboolean attach (pid_t pid, const List source_search_directories); - + + /** + * ianjuta_debugger_set_working_directory: + * @obj: Self + * @dir: working program directory + * @err: Error propagation and reporting. + * + * Set program working directory. + * + * Returns: TRUE if sucessful, other FALSE. + */ + gboolean set_working_directory (const gchar *dir); + + /** + * ianjuta_debugger_set_environment: + * @obj: Self + * @env: List environment variable + * @err: Error propagation and reporting + * + * Set environment variable + * + * Returns: TRUE if sucessfull, other FALSE. + */ + gboolean set_environment (const List env); + /** * ianjuta_debugger_start: * @obj: Self diff --git a/plugins/debug-manager/anjuta-debug-manager.glade b/plugins/debug-manager/anjuta-debug-manager.glade index 45e325c6..fdfc845a 100644 --- a/plugins/debug-manager/anjuta-debug-manager.glade +++ b/plugins/debug-manager/anjuta-debug-manager.glade @@ -1006,7 +1006,7 @@ True 5 - 4 + 6 3 5 5 @@ -1021,8 +1021,8 @@ 3 - 3 - 4 + 5 + 6 GTK_FILL @@ -1038,8 +1038,8 @@ 3 - 2 - 3 + 4 + 5 GTK_FILL @@ -1058,6 +1058,7 @@ 1 2 GTK_FILL + @@ -1084,7 +1085,7 @@ 1 2 - GTK_FILL + 3 @@ -1115,10 +1116,121 @@ + + + True + + 0 + Working Directory: + + + 2 + 3 + GTK_FILL + + + + + + True + + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER + Choose a working directory + + + 1 + 3 + 2 + 3 + + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_OUT + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + GTK_BUTTONBOX_START + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-add + True + 0 + + + + + True + False + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-remove + True + 0 + + + 1 + + + + + False + False + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Environment Variables: + + + label_item + + + + + 3 + 3 + 4 + + - False - False 5 2 diff --git a/plugins/debug-manager/command.c b/plugins/debug-manager/command.c index 7d3180f3..83d4f5c2 100644 --- a/plugins/debug-manager/command.c +++ b/plugins/debug-manager/command.c @@ -56,13 +56,15 @@ typedef enum INSPECT_MEMORY_COMMAND, DISASSEMBLE_COMMAND, LIST_REGISTER_COMMAND, + SET_WORKING_DIRECTORY_COMMAND, + SET_ENVIRONMENT_COMMAND, UNLOAD_COMMAND, /* Program loaded */ START_COMMAND, BREAK_LINE_COMMAND, /* Program loaded - Program stopped */ BREAK_FUNCTION_COMMAND, - BREAK_ADDRESS_COMMAND, + BREAK_ADDRESS_COMMAND, /* 0x10 */ ENABLE_BREAK_COMMAND, - IGNORE_BREAK_COMMAND, /* 0x10 */ + IGNORE_BREAK_COMMAND, CONDITION_BREAK_COMMAND, REMOVE_BREAK_COMMAND, LIST_BREAK_COMMAND, @@ -76,9 +78,9 @@ typedef enum RUN_COMMAND, RUN_TO_COMMAND, STEPI_IN_COMMAND, - STEPI_OVER_COMMAND, + STEPI_OVER_COMMAND, /* 0x20 */ RUN_TO_ADDRESS_COMMAND, - EXIT_COMMAND, /* 0x20 */ + EXIT_COMMAND, HANDLE_SIGNAL_COMMAND, LIST_LOCAL_COMMAND, LIST_ARG_COMMAND, @@ -92,9 +94,9 @@ typedef enum SET_FRAME_COMMAND, LIST_FRAME_COMMAND, UPDATE_REGISTER_COMMAND, - WRITE_REGISTER_COMMAND, + WRITE_REGISTER_COMMAND, /* 0x30 */ EVALUATE_COMMAND, - INSPECT_COMMAND, /* 0x30 */ + INSPECT_COMMAND, PRINT_COMMAND, CREATE_VARIABLE, EVALUATE_VARIABLE, @@ -134,6 +136,12 @@ typedef enum DMA_LIST_REGISTER_COMMAND = LIST_REGISTER_COMMAND | NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED | NEED_PROGRAM_RUNNING, + DMA_SET_WORKING_DIRECTORY_COMMAND = + SET_WORKING_DIRECTORY_COMMAND | + NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED, + DMA_SET_ENVIRONMENT_COMMAND = + SET_ENVIRONMENT_COMMAND | + NEED_DEBUGGER_STARTED | NEED_PROGRAM_LOADED, DMA_UNLOAD_COMMAND = UNLOAD_COMMAND | START_DEBUGGER | NEED_PROGRAM_LOADED | NEED_PROGRAM_STOPPED, @@ -341,6 +349,8 @@ struct _DmaQueueCommand gchar *name; gchar *value; } var; + GList *env; + gchar *dir; } data; struct _DmaQueueCommand *next; }; @@ -394,6 +404,16 @@ dma_command_new (DmaDebuggerCommand cmd_type,...) break; case ABORT_COMMAND: break; + case SET_WORKING_DIRECTORY_COMMAND: + cmd->data.dir = g_strdup (va_arg (args, gchar *)); + break; + case SET_ENVIRONMENT_COMMAND: + for (list = va_arg (args, GList *); list != NULL; list = g_list_next (list)) + { + cmd->data.env = g_list_prepend (cmd->data.env, g_strdup (list->data)); + } + cmd->data.env = g_list_reverse (cmd->data.env); + break; case START_COMMAND: cmd->data.start.args = g_strdup (va_arg (args, gchar *)); cmd->data.start.terminal = va_arg (args, gboolean); @@ -630,6 +650,18 @@ dma_queue_attach (DmaDebuggerQueue *self, pid_t pid, const GList *search_dirs) } gboolean +dma_queue_set_working_directory(DmaDebuggerQueue *self, const gchar *directory) +{ + return dma_debugger_queue_append (self, dma_command_new (DMA_SET_WORKING_DIRECTORY_COMMAND, directory)); +} + +gboolean +dma_queue_set_environment(DmaDebuggerQueue *self, const GList *variables) +{ + return dma_debugger_queue_append (self, dma_command_new (DMA_SET_ENVIRONMENT_COMMAND, variables)); +} + +gboolean dma_queue_start (DmaDebuggerQueue *self, const gchar *args, gboolean terminal, gboolean stop) { return dma_debugger_queue_append (self, dma_command_new (DMA_START_COMMAND, args, terminal, stop)); @@ -1015,6 +1047,13 @@ dma_command_free (DmaQueueCommand *cmd) g_list_foreach (cmd->data.load.dirs, (GFunc)g_free, NULL); g_list_free (cmd->data.load.dirs); break; + case SET_WORKING_DIRECTORY_COMMAND: + if (cmd->data.dir) g_free (cmd->data.dir); + break; + case SET_ENVIRONMENT_COMMAND: + g_list_foreach (cmd->data.env, (GFunc)g_free, NULL); + g_list_free (cmd->data.env); + break; case ATTACH_COMMAND: g_list_foreach (cmd->data.attach.dirs, (GFunc)g_free, NULL); g_list_free (cmd->data.attach.dirs); @@ -1114,6 +1153,12 @@ dma_command_run (DmaQueueCommand *cmd, IAnjutaDebugger *debugger, case ATTACH_COMMAND: ret = ianjuta_debugger_attach (debugger, cmd->data.attach.pid, cmd->data.load.dirs, err); break; + case SET_WORKING_DIRECTORY_COMMAND: + ret = ianjuta_debugger_set_working_directory (debugger, cmd->data.dir, err); + break; + case SET_ENVIRONMENT_COMMAND: + ret = ianjuta_debugger_set_environment (debugger, cmd->data.env, err); + break; case UNLOAD_COMMAND: ret = ianjuta_debugger_unload (debugger, err); break; @@ -1316,6 +1361,8 @@ dma_command_callback (DmaQueueCommand *cmd, const gpointer data, GError *err) case QUIT_COMMAND: case ABORT_COMMAND: case START_COMMAND: + case SET_WORKING_DIRECTORY_COMMAND: + case SET_ENVIRONMENT_COMMAND: case RUN_COMMAND: case RUN_TO_COMMAND: case STEP_IN_COMMAND: diff --git a/plugins/debug-manager/command.h b/plugins/debug-manager/command.h index fd45e6bf..0da66a0c 100644 --- a/plugins/debug-manager/command.h +++ b/plugins/debug-manager/command.h @@ -59,6 +59,8 @@ typedef enum /* Create a new command structure and append to command queue */ gboolean dma_queue_initialize (DmaDebuggerQueue *self); gboolean dma_queue_load (DmaDebuggerQueue *self, const gchar *file, const gchar* mime_type, const GList *search_dirs); +gboolean dma_queue_set_working_directory (DmaDebuggerQueue *self, const gchar *directory); +gboolean dma_queue_set_environment (DmaDebuggerQueue *self, const GList *variables); gboolean dma_queue_attach (DmaDebuggerQueue *self, pid_t pid, const GList *search_dirs); gboolean dma_queue_start (DmaDebuggerQueue *self, const gchar *args, gboolean terminal, gboolean stop); gboolean dma_queue_unload (DmaDebuggerQueue *self); diff --git a/plugins/debug-manager/start.c b/plugins/debug-manager/start.c index 73b1285d..a572b344 100644 --- a/plugins/debug-manager/start.c +++ b/plugins/debug-manager/start.c @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include #include #include @@ -97,6 +100,12 @@ static char *column_names[COLUMNS_NB] = { N_("Pid"), N_("User"), N_("Time"), N_("Command") }; +enum { + VARIABLE_COLUMN, + VALUE_COLUMN, + VAR_COLUMNS_NB +}; + struct _AddSourceDialog { GtkTreeView *tree; @@ -116,12 +125,14 @@ struct _DmaStart DmaDebuggerQueue *debugger; - gchar* target_uri; - gchar* program_args; gboolean run_in_terminal; gboolean stop_at_beginning; GList *source_dirs; + GList *environment_vars; + GList *recent_target; + GList *recent_dirs; + GList *recent_args; }; /* Widgets found in glade file @@ -133,6 +144,10 @@ struct _DmaStart #define PARAMETER_COMBO "parameter_combo" #define TARGET_COMBO "target_combo" #define TARGET_SELECT_SIGNAL "on_select_target_clicked" +#define ADD_VAR_BUTTON "add_button" +#define REMOVE_VAR_BUTTON "remove_button" +#define VAR_TREEVIEW "environment_treeview" +#define DIR_CHOOSER "working_dir_chooser" #define ADD_SOURCE_DIALOG "source_paths_dialog" #define SOURCE_ENTRY "src_entry" @@ -144,6 +159,8 @@ struct _DmaStart #define ANJUTA_RESPONSE_SELECT_TARGET 0 +#define MAX_RECENT_ITEM 12 + static void attach_process_clear (AttachProcess * ap, gint ClearRequest); /* Helper functions @@ -224,86 +241,148 @@ free_source_directories (GList *dirs) g_list_free (dirs); } +static gboolean +save_all_files_and_continue (AnjutaPlugin *plugin) +{ + IAnjutaDocumentManager *docman; + IAnjutaFileSavable* save; + + docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager, NULL); + + /* No document manager, so no file to save */ + if (docman != NULL) + { + save = IANJUTA_FILE_SAVABLE (docman); + if (save != NULL) + { + if (ianjuta_file_savable_is_dirty (save, NULL)) + { + gboolean yes; + + yes = anjuta_util_dialog_boolean_question (GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell), + _("Some files are not saved. Do you want to save all them before starting the debugger?")); + + if (yes) + { + ianjuta_file_savable_save (save, NULL); + } + + return yes; + } + } + } + + return TRUE; +} + +static gboolean +build_target (AnjutaPlugin* plugin, const gchar *target_uri) +{ + IAnjutaBuildable *buildable; + + buildable = anjuta_shell_get_interface (plugin->shell, IAnjutaBuildable, NULL); + if (buildable != NULL) + { + gchar *filename; + gchar *dirname; + + filename = gnome_vfs_get_local_path_from_uri (target_uri); + g_free (filename); + dirname = g_path_get_dirname (filename); + ianjuta_buildable_build (buildable, dirname, NULL); + g_free (dirname); + } + + return TRUE; +} + /* Callback for saving session *---------------------------------------------------------------------------*/ static void -on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *this) +anjuta_session_set_limited_string_list (AnjutaSession *session, const gchar *section, const gchar *key, GList **value) +{ + GList *node; + + while ((node = g_list_nth (*value, MAX_RECENT_ITEM)) != NULL) + { + g_free (node->data); + *value = g_list_delete_link (*value, node); + } + anjuta_session_set_string_list (session, section, key, *value); +} + +static void +on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *self) { if (phase != ANJUTA_SESSION_PHASE_NORMAL) return; - if (this->program_args) - { - gchar *arg; - anjuta_session_set_string (session, "Execution", "Program arguments", this->program_args); - arg = anjuta_session_get_string (session, "Execution", "Program arguments"); - } - if (this->target_uri) - { - gchar *uri; - anjuta_session_set_string (session, "Execution", "Program uri", this->target_uri); - uri = anjuta_session_get_string (session, "Execution", "Program uri"); - } - anjuta_session_set_int (session, "Execution", "Run in terminal", this->run_in_terminal + 1); - anjuta_session_set_int (session, "Execution", "Stop at beginning", this->stop_at_beginning + 1); - if (this->source_dirs) - { - anjuta_session_set_string_list (session, "Debugger", "Source directories", this->source_dirs); - } + anjuta_session_set_limited_string_list (session, "Debugger", "Program arguments", &self->recent_args); + anjuta_session_set_limited_string_list (session, "Debugger", "Program uri", &self->recent_target); + anjuta_session_set_int (session, "Execution", "Run in terminal", self->run_in_terminal + 1); + anjuta_session_set_int (session, "Debugger", "Stop at beginning", self->stop_at_beginning + 1); + anjuta_session_set_string_list (session, "Debugger", "Source directories", self->source_dirs); + anjuta_session_set_string_list (session, "Debugger", "Working directories", self->recent_dirs); + anjuta_session_set_string_list (session, "Debugger", "Environment variables", self->environment_vars); } -static void on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *this) +static void on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *self) { - gchar *program_args; - gchar *target_uri; gint run_in_terminal; gint stop_at_beginning; if (phase != ANJUTA_SESSION_PHASE_NORMAL) return; - program_args = anjuta_session_get_string (session, "Execution", "Program arguments"); - if (this->program_args) - { - g_free (this->program_args); - this->program_args = NULL; - } - if (program_args) - { - this->program_args = program_args; - } + if (self->recent_args != NULL) + { + g_list_foreach (self->recent_args, (GFunc)g_free, NULL); + g_list_free (self->recent_args); + } + self->recent_args = anjuta_session_get_string_list (session, "Debugger", "Program arguments"); - target_uri = anjuta_session_get_string (session, "Execution", "Program uri"); - if (this->target_uri) - { - g_free (this->target_uri); - this->target_uri = NULL; - } - if (target_uri) - { - this->target_uri = target_uri; - } + if (self->recent_target != NULL) + { + g_list_foreach (self->recent_target, (GFunc)g_free, NULL); + g_list_free (self->recent_target); + } + self->recent_target = anjuta_session_get_string_list (session, "Debugger", "Program uri"); /* The flag is store as 1 == FALSE, 2 == TRUE */ run_in_terminal = anjuta_session_get_int (session, "Execution", "Run in terminal"); if (run_in_terminal == 0) - this->run_in_terminal = TRUE; /* Default value */ + self->run_in_terminal = TRUE; /* Default value */ else - this->run_in_terminal = run_in_terminal - 1; + self->run_in_terminal = run_in_terminal - 1; - stop_at_beginning = anjuta_session_get_int (session, "Execution", "Stop at beginning"); + stop_at_beginning = anjuta_session_get_int (session, "Debugger", "Stop at beginning"); if (stop_at_beginning == 0) - this->stop_at_beginning = TRUE; /* Default value */ + self->stop_at_beginning = TRUE; /* Default value */ else - this->stop_at_beginning = stop_at_beginning - 1; + self->stop_at_beginning = stop_at_beginning - 1; + /* Initialize source_dirs */ - if (this->source_dirs != NULL) + if (self->source_dirs != NULL) + { + g_list_foreach (self->source_dirs, (GFunc)g_free, NULL); + g_list_free (self->source_dirs); + } + self->source_dirs = anjuta_session_get_string_list (session, "Debugger", "Source directories"); + + if (self->recent_dirs != NULL) + { + g_list_foreach (self->recent_dirs, (GFunc)g_free, NULL); + g_list_free (self->recent_dirs); + } + self->recent_dirs = anjuta_session_get_string_list (session, "Debugger", "Working directories"); + + if (self->environment_vars != NULL) { - g_list_foreach (this->source_dirs, (GFunc)g_free, NULL); - g_list_free (this->source_dirs); + g_list_foreach (self->environment_vars, (GFunc)g_free, NULL); + g_list_free (self->environment_vars); } - this->source_dirs = anjuta_session_get_string_list (session, "Debugger", "Source directories"); + self->environment_vars = anjuta_session_get_string_list (session, "Debugger", "Environment variables"); } /* Attach to process private functions @@ -841,12 +920,6 @@ attach_process_destroy (AttachProcess * ap) /* Load file private functions *---------------------------------------------------------------------------*/ -static void -on_select_target (GtkButton *button, gpointer user_data) -{ - gtk_dialog_response (GTK_DIALOG (user_data), ANJUTA_RESPONSE_SELECT_TARGET); -} - static gboolean dma_start_load_uri (DmaStart *this) { @@ -855,32 +928,34 @@ dma_start_load_uri (DmaStart *this) gchar *mime_type; gchar *filename; + if (this->recent_target == NULL) return FALSE; /* Missing URI */ + if (!dma_quit_debugger (this)) return FALSE; - if ((this->target_uri == NULL) || (*(this->target_uri) == '\0')) - { - /* Missing URI */ - return FALSE; - } - vfs_uri = gnome_vfs_uri_new (this->target_uri); + vfs_uri = gnome_vfs_uri_new ((const gchar *)(this->recent_target->data)); - g_return_if_fail (vfs_uri != NULL); + g_return_val_if_fail (vfs_uri != NULL, TRUE); if (!gnome_vfs_uri_is_local (vfs_uri)) return FALSE; - + + if (save_all_files_and_continue (this->plugin)) + { + build_target (this->plugin, (const gchar *)(this->recent_target->data)); + } + search_dirs = get_source_directories (this->plugin); - - mime_type = gnome_vfs_get_mime_type (this->target_uri); + + mime_type = gnome_vfs_get_mime_type ((const gchar *)(this->recent_target->data)); if (mime_type == NULL) { anjuta_util_dialog_error(GTK_WINDOW (this->plugin->shell), - _("Unable to open %s. Debugger cannot start."), this->target_uri); + _("Unable to open %s. Debugger cannot start."), (const gchar *)(this->recent_target->data)); return FALSE; } - filename = gnome_vfs_get_local_path_from_uri (this->target_uri); - + filename = gnome_vfs_get_local_path_from_uri ((const gchar *)(this->recent_target->data)); + dma_queue_load (this->debugger, filename, mime_type, this->source_dirs); - + g_free (filename); g_free (mime_type); gnome_vfs_uri_unref (vfs_uri); @@ -889,6 +964,156 @@ dma_start_load_uri (DmaStart *this) return TRUE; } +/* Run program dialog + *---------------------------------------------------------------------------*/ + +static void +on_select_target (GtkButton *button, gpointer user_data) +{ + gtk_dialog_response (GTK_DIALOG (user_data), ANJUTA_RESPONSE_SELECT_TARGET); +} + +static void +on_environment_add_button (GtkButton *button, GtkTreeView *view) +{ + GtkTreeIter iter; + GtkListStore *model; + GtkTreeViewColumn *column; + GtkTreePath *path; + + model = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + gtk_list_store_append (model, &iter); + path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); + column = gtk_tree_view_get_column (view, 0); + gtk_tree_view_set_cursor (view, path, column ,TRUE); + gtk_tree_path_free (path); +} + +static void +on_environment_remove_button (GtkButton *button, GtkTreeView *view) +{ + GtkTreeIter iter; + GtkTreeSelection* sel; + + sel = gtk_tree_view_get_selection (view); + if (gtk_tree_selection_get_selected (sel, NULL, &iter)) + { + GtkListStore *model; + model = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + + gtk_list_store_remove (model, &iter); + } +} + +static void +on_environment_variable_edited (GtkCellRendererText *cell, + gchar *path, + gchar *text, + GtkTreeView *view) +{ + GtkTreeIter iter; + GtkListStore *model; + + model = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path)) + { + GtkTreeViewColumn *column; + GtkTreePath *path; + gtk_list_store_set (model, &iter, VARIABLE_COLUMN, text, -1); + path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); + column = gtk_tree_view_get_column (view, 1); + gtk_tree_view_set_cursor (view, path, column ,TRUE); + } +} + +static void +on_environment_selection_changed (GtkTreeSelection *selection, GtkWidget *button) +{ + gtk_widget_set_sensitive (button, gtk_tree_selection_get_selected (selection, NULL, NULL)); +} + +static void +on_environment_value_edited (GtkCellRendererText *cell, + gchar *path, + gchar *text, + GtkTreeView *view) +{ + GtkTreeIter iter; + GtkListStore *model; + + model = GTK_LIST_STORE (gtk_tree_view_get_model (view)); + if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path)) + { + gtk_list_store_set (model, &iter, VALUE_COLUMN, text, -1); + } +} + +static void +on_add_string_in_model (gpointer data, gpointer user_data) +{ + GtkListStore* model = (GtkListStore *)user_data; + GtkTreeIter iter; + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, 0, (const gchar *)data, -1); +} + +static void +on_add_uri_in_model (gpointer data, gpointer user_data) +{ + GtkListStore* model = (GtkListStore *)user_data; + GtkTreeIter iter; + gchar *local; + + local = gnome_vfs_get_local_path_from_uri ((const char *)data); + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, 0, local, -1); + g_free (local); +} + +static void +on_add_variable_in_model (gpointer data, gpointer user_data) +{ + GtkListStore* model = (GtkListStore *)user_data; + GtkTreeIter iter; + gchar **var; + + var = g_strsplit ((const gchar *)data, "=", 2); + + if (var) + { + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, 0, var[0], 1, var[1], -1); + g_strfreev (var); + } +} + +static void +on_add_directory_in_chooser (gpointer data, gpointer user_data) +{ + GtkFileChooser* chooser = (GtkFileChooser *)user_data; + gchar *local; + + local = gnome_vfs_get_local_path_from_uri ((const char *)data); + gtk_file_chooser_add_shortcut_folder (chooser, (const gchar *)local, NULL); + g_free (local); +} + +static gboolean +on_add_variable_in_list (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) +{ + GList** list = (GList **)user_data; + gchar* name; + gchar* value; + + gtk_tree_model_get (model, iter, 0, &name, 1, &value, -1); + *list = g_list_prepend (*list, g_strconcat(name, "=", value, NULL)); + g_free (name); + g_free (value); + + return FALSE; +} + static gboolean dma_set_parameters (DmaStart *this) { @@ -901,7 +1126,12 @@ dma_set_parameters (DmaStart *this) GtkComboBox *target; gint response; GtkTreeModel* model; - GtkTreeIter iter; + GtkTreeView *vars; + GtkFileChooser *dirs; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkTreeSelection *selection; + GObject *button; GValue value = {0,}; const gchar *project_root_uri; @@ -918,18 +1148,28 @@ dma_set_parameters (DmaStart *this) stop_at_beginning = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gxml, STOP_AT_BEGINNING_CHECK_BUTTON)); params = GTK_COMBO_BOX (glade_xml_get_widget (gxml, PARAMETER_COMBO)); target = GTK_COMBO_BOX (glade_xml_get_widget (gxml, TARGET_COMBO)); + vars = GTK_TREE_VIEW (glade_xml_get_widget (gxml, VAR_TREEVIEW)); + dirs = GTK_FILE_CHOOSER (glade_xml_get_widget (gxml, DIR_CHOOSER)); + + /* Connect signals */ glade_xml_signal_connect_data (gxml, TARGET_SELECT_SIGNAL, GTK_SIGNAL_FUNC (on_select_target), dlg); + button = G_OBJECT (glade_xml_get_widget (gxml, ADD_VAR_BUTTON)); + g_signal_connect (button, "clicked", G_CALLBACK (on_environment_add_button), vars); + button = G_OBJECT (glade_xml_get_widget (gxml, REMOVE_VAR_BUTTON)); + g_signal_connect (button, "clicked", G_CALLBACK (on_environment_remove_button), vars); + selection = gtk_tree_view_get_selection (vars); + g_signal_connect (selection, "changed", G_CALLBACK (on_environment_selection_changed), GTK_WIDGET (button)); + g_object_unref (gxml); /* Fill parameter combo box */ model = GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING)); gtk_combo_box_set_model (params, model); gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(params), 0); - if (this->program_args != NULL) + g_list_foreach (this->recent_args, on_add_string_in_model, model); + if (this->recent_args != NULL) { - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, this->program_args, -1); - gtk_entry_set_text (GTK_ENTRY (GTK_BIN (params)->child), this->program_args); + gtk_entry_set_text (GTK_ENTRY (GTK_BIN (params)->child), (const char *)this->recent_args->data); } g_object_unref (model); @@ -937,6 +1177,7 @@ dma_set_parameters (DmaStart *this) model = GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING)); gtk_combo_box_set_model (target, model); gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(target), 0); + g_list_foreach (this->recent_target, on_add_uri_in_model, model); anjuta_shell_get_value (this->plugin->shell, "project_root_uri", &value, NULL); project_root_uri = G_VALUE_HOLDS_STRING (&value) ? g_value_get_string (&value) : NULL; @@ -960,10 +1201,16 @@ dma_set_parameters (DmaStart *this) for (node = exec_targets; node; node = g_list_next (node)) { - if ((this->target_uri == NULL) || (strcmp(this->target_uri, node->data) != 0)) + GList *target; + for (target = this->recent_target; target; target = g_list_next (target)) + { + if (strcmp ((const gchar *)target->data, node->data) == 0) break; + } + if (target == NULL) { - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, node->data, -1); + on_add_uri_in_model (node->data, model); + /*gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, node->data, -1);*/ } g_free (node->data); } @@ -972,20 +1219,35 @@ dma_set_parameters (DmaStart *this) } g_object_unref (model); - if (this->target_uri != NULL) + if (this->recent_target != NULL) { - gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, this->target_uri, -1); - gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), this->target_uri); - } - else if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) - { - gchar *txt; + gchar *local; - gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &txt, -1); - gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), txt); - g_free (txt); + local = gnome_vfs_get_local_path_from_uri ((const char *)this->recent_target->data); + gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), local); + g_free (local); } + /* Fill working directory list */ + g_list_foreach (this->recent_dirs, on_add_directory_in_chooser, dirs); + + /* Fill environment variable list */ + model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING)); + gtk_tree_view_set_model (vars, model); + g_list_foreach (this->environment_vars, on_add_variable_in_model, model); + g_object_unref (model); + + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", (GCallback) on_environment_variable_edited, vars); + column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", 0, NULL); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column (vars, column); + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", (GCallback) on_environment_value_edited, vars); + column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer, "text", 1, NULL); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column (vars, column); /* Set terminal option */ if (this->run_in_terminal) gtk_toggle_button_set_active (term, TRUE); @@ -1003,26 +1265,57 @@ dma_set_parameters (DmaStart *this) case GTK_RESPONSE_APPLY: { const gchar *arg; - const gchar *uri; + const gchar *filename; + gchar *uri; + GList *find; - if (this->program_args != NULL) g_free (this->program_args); arg = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (params)->child)); - this->program_args = g_strdup (arg); + if (arg != NULL) + { + find = g_list_find_custom(this->recent_args, arg, (GCompareFunc)strcmp); + if (find) + { + g_free (find->data); + this->recent_args = g_list_delete_link (this->recent_args, find); + } + this->recent_args = g_list_prepend (this->recent_args, g_strdup (arg)); + } - uri = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (target)->child)); - if (this->target_uri != NULL) + filename = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (target)->child)); + if (filename != NULL) { - if (strcmp(uri, this->target_uri) != 0) + uri = gnome_vfs_get_uri_from_local_path (filename); + if (uri != NULL) { - g_free (this->target_uri); - this->target_uri = g_strdup (uri); + find = g_list_find_custom (this->recent_target, uri, (GCompareFunc)strcmp); + if (find) + { + g_free (find->data); + this->recent_target = g_list_delete_link (this->recent_target, find); + } + this->recent_target = g_list_prepend (this->recent_target, uri); } } - else + + uri = gtk_file_chooser_get_uri (dirs); + if (uri != NULL) { - this->target_uri = g_strdup (uri); + find = g_list_find_custom(this->recent_dirs, uri, (GCompareFunc)strcmp); + if (find) + { + g_free (find->data); + this->recent_dirs = g_list_delete_link (this->recent_dirs, find); + } + this->recent_dirs = g_list_prepend (this->recent_dirs, uri); } + g_list_foreach (this->environment_vars, (GFunc)g_free, NULL); + g_list_free (this->environment_vars); + this->environment_vars = NULL; + model = gtk_tree_view_get_model (vars); + gtk_tree_model_foreach (GTK_TREE_MODEL (model), on_add_variable_in_list, &this->environment_vars); + this->environment_vars = g_list_reverse (this->environment_vars); + this->run_in_terminal = gtk_toggle_button_get_active (term); this->stop_at_beginning = gtk_toggle_button_get_active (stop_at_beginning); break; @@ -1048,27 +1341,10 @@ dma_set_parameters (DmaStart *this) if (response == GTK_RESPONSE_OK) { - gchar* uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (sel_dlg)); - - if (this->target_uri != NULL) - { - if (strcmp(uri, this->target_uri) != 0) - { - g_free (this->target_uri); - this->target_uri = uri; - } - else - { - g_free (uri); - } - } - else - { - this->target_uri = uri; - } - - gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), this->target_uri); + gchar* filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (sel_dlg)); + gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), filename); + g_free (filename); } gtk_widget_destroy (GTK_WIDGET (sel_dlg)); @@ -1103,19 +1379,6 @@ on_add_source_in_list (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter } static void -on_add_source_in_model (gpointer data, gpointer user_data) -{ - GtkListStore* model = (GtkListStore *)user_data; - GtkTreeIter iter; - gchar *local; - - local = gnome_vfs_get_local_path_from_uri ((const char *)data); - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, 0, local, -1); - g_free (local); -} - -static void on_source_add_button (GtkButton *button, AddSourceDialog *dlg) { GtkTreeIter iter; @@ -1229,7 +1492,7 @@ add_source_show (DmaStart *this) gtk_window_set_transient_for (GTK_WINDOW (widget), parent); /* Initialize source path list */ - g_list_foreach (this->source_dirs, on_add_source_in_model, dlg.model); + g_list_foreach (this->source_dirs, on_add_uri_in_model, dlg.model); /* Run dialog */ for (;;) @@ -1248,7 +1511,7 @@ add_source_show (DmaStart *this) break; case GTK_RESPONSE_CANCEL: gtk_list_store_clear (dlg.model); - g_list_foreach (this->source_dirs, on_add_source_in_model, dlg.model); + g_list_foreach (this->source_dirs, on_add_uri_in_model, dlg.model); continue; default: break; @@ -1314,22 +1577,30 @@ gboolean dma_run_target (DmaStart *this) { if (!dma_set_parameters (this)) return FALSE; - - if (!dma_start_load_uri (this)) return FALSE; - - dma_queue_start (this->debugger, this->program_args == NULL ? "" : this->program_args, this->run_in_terminal, this->stop_at_beginning); - - return TRUE; + + return dma_rerun_target (this); } gboolean dma_rerun_target (DmaStart *this) { - if (this->target_uri == NULL) return FALSE; - + gchar *dir; + if (!dma_start_load_uri (this)) return FALSE; - dma_queue_start (this->debugger, this->program_args == NULL ? "" : this->program_args, this->run_in_terminal, this->stop_at_beginning); + if (this->recent_dirs != NULL) + { + dir = gnome_vfs_get_local_path_from_uri ((const gchar *)(this->recent_dirs->data)); + } + else + { + dir = NULL; + } + dma_queue_set_working_directory (this->debugger, dir); + g_free (dir); + dma_queue_set_environment (this->debugger, this->environment_vars); + + dma_queue_start (this->debugger, this->recent_args == NULL ? "" : (const char *)this->recent_args->data,this->run_in_terminal, this->stop_at_beginning); return TRUE; } @@ -1361,13 +1632,18 @@ dma_start_free (DmaStart *this) { g_signal_handlers_disconnect_by_func (this->plugin->shell, G_CALLBACK (on_session_save), this); g_signal_handlers_disconnect_by_func (this->plugin->shell, G_CALLBACK (on_session_load), this); - if (this->source_dirs != NULL) - { - g_list_foreach (this->source_dirs, (GFunc)g_free, NULL); - g_list_free (this->source_dirs); - } - if (this->program_args != NULL) g_free (this->program_args); - if (this->target_uri != NULL) g_free (this->target_uri); + g_list_foreach (this->source_dirs, (GFunc)g_free, NULL); + g_list_free (this->source_dirs); + g_list_foreach (this->recent_target, (GFunc)g_free, NULL); + g_list_free (this->recent_target); + g_list_foreach (this->recent_args, (GFunc)g_free, NULL); + g_list_free (this->recent_args); + g_list_foreach (this->recent_args, (GFunc)g_free, NULL); + g_list_free (this->recent_args); + g_list_foreach (this->recent_dirs, (GFunc)g_free, NULL); + g_list_free (this->recent_dirs); + g_list_foreach (this->environment_vars, (GFunc)g_free, NULL); + g_list_free (this->environment_vars); g_free (this); } diff --git a/plugins/gdb/debugger.c b/plugins/gdb/debugger.c index 7161831a..76e3d12c 100644 --- a/plugins/gdb/debugger.c +++ b/plugins/gdb/debugger.c @@ -726,6 +726,45 @@ debugger_load_core (Debugger *debugger, const gchar *core) g_free (command); } +/* Set environment + *---------------------------------------------------------------------------*/ + +gboolean +debugger_set_working_directory (Debugger *debugger, const gchar *directory) +{ + gchar *buff; + + DEBUG_PRINT ("In function: set_working_directory()"); + + g_return_val_if_fail (IS_DEBUGGER (debugger), FALSE); + + buff = g_strdup_printf ("-environment-cd %s", directory); + debugger_queue_command (debugger, buff, FALSE, FALSE, NULL, NULL, NULL); + g_free (buff); + + return TRUE; +} + +gboolean +debugger_set_environment (Debugger *debugger, const GList *variables) +{ + gchar *buff; + GList *node; + + DEBUG_PRINT ("In function: set_environment()"); + + g_return_val_if_fail (IS_DEBUGGER (debugger), FALSE); + + for (node = variables; node != NULL; node = g_list_next (node)) + { + buff = g_strdup_printf("set environment %s", (const char *)node->data); + debugger_queue_command (debugger, buff, FALSE, FALSE, NULL, NULL, NULL); + g_free (buff); + } + + return TRUE; +} + gboolean debugger_start (Debugger *debugger, const GList *search_dirs, const gchar *prog, gboolean is_libtool_prog) diff --git a/plugins/gdb/debugger.h b/plugins/gdb/debugger.h index 50aaa319..146fce6d 100644 --- a/plugins/gdb/debugger.h +++ b/plugins/gdb/debugger.h @@ -107,6 +107,10 @@ void debugger_load_core (Debugger *debugger, const gchar *core); void debugger_attach_process (Debugger *debugger, pid_t pid); void debugger_detach_process (Debugger *debugger); +/* Environment */ +gboolean debugger_set_working_directory (Debugger *debugger, const gchar *directory); +gboolean debugger_set_environment (Debugger *debugger, const GList *variables); + /* Execution */ void debugger_start_program (Debugger *debugger, const gchar* args, const gchar* tty, gboolean stop); void debugger_stop_program (Debugger *debugger); diff --git a/plugins/gdb/plugin.c b/plugins/gdb/plugin.c index 6cecb0ef..870fe56e 100644 --- a/plugins/gdb/plugin.c +++ b/plugins/gdb/plugin.c @@ -350,6 +350,26 @@ idebugger_unload (IAnjutaDebugger *plugin, GError **err) } static gboolean +idebugger_set_working_directory (IAnjutaDebugger *plugin, const gchar *directory, GError **err) +{ + GdbPlugin *self = ANJUTA_PLUGIN_GDB (plugin); + + debugger_set_working_directory (self->debugger, directory); + + return TRUE; +} + +static gboolean +idebugger_set_environment (IAnjutaDebugger *plugin, const GList *variables, GError **err) +{ + GdbPlugin *self = ANJUTA_PLUGIN_GDB (plugin); + + debugger_set_environment (self->debugger, variables); + + return TRUE; +} + +static gboolean idebugger_attach (IAnjutaDebugger *plugin, pid_t pid, const GList *search_dirs, GError **err) { GdbPlugin *this = ANJUTA_PLUGIN_GDB (plugin); @@ -733,6 +753,8 @@ idebugger_iface_init (IAnjutaDebuggerIface *iface) iface->get_state = idebugger_get_state; iface->attach = idebugger_attach; iface->load = idebugger_load; + iface->set_working_directory = idebugger_set_working_directory; + iface->set_environment = idebugger_set_environment; iface->start = idebugger_start; iface->unload = idebugger_unload; iface->quit = idebugger_quit; -- 2.11.4.GIT